1 ========================================================================
2 CONSOLE APPLICATION : VBAutomateWord Project Overview
3 ========================================================================
5 /////////////////////////////////////////////////////////////////////////////
8 The VBAutomateWord example demonstrates the use of Visual Basic.NET codes to
9 create a Microsoft Word instance, create a new document, insert a paragraph
10 and a table, save the document, close the Microsoft Word application and then
11 clean up unmanaged COM resources.
13 Office automation is based on Component Object Model (COM). When you call a
14 COM object of Office from managed code, a Runtime Callable Wrapper (RCW) is
15 automatically created. The RCW marshals calls between the .NET application
16 and the COM object. The RCW keeps a reference count on the COM object. If
17 all references have not been released on the RCW, the COM object of Office
18 does not quit and may cause the Office application not to quit after your
19 automation. In order to make sure that the Office application quits cleanly,
20 the sample demonstrates two solutions.
22 Solution1.AutomateWord demonstrates automating Microsoft Word application by
23 using Microsoft Word Primary Interop Assembly (PIA) and explicitly assigning
24 each COM accessor object to a new varaible that you would explicitly call
25 Marshal.FinalReleaseComObject to release it at the end.
27 Solution2.AutomateWord demonstrates automating Microsoft Word application by
28 using Microsoft Word PIA and forcing a garbage collection as soon as the
29 automation function is off the stack (at which point the RCW objects are no
30 longer rooted) to clean up RCWs and release COM objects.
33 /////////////////////////////////////////////////////////////////////////////
36 You must run this code sample on a computer that has Microsoft Word 2007
40 /////////////////////////////////////////////////////////////////////////////
43 The following steps walk through a demonstration of the Word automation
44 sample that starts a Microsoft Word instance, creates a new document,
45 inserts a paragraph and a table, saves the document, and quits the Microsoft
46 Word application cleanly.
48 Step1. After you successfully build the sample project in Visual Studio 2008,
49 you will get the application: VBAutomateWord.exe.
51 Step2. Open Windows Task Manager (Ctrl+Shift+Esc) to confirm that no
52 winword.exe is running.
54 Step3. Run the application. It should print the following content in the
55 console window if no error is thrown.
57 Word.Application is started
58 A new document is created
60 Save and close the document
61 Quit the Word application
63 Word.Application is started
66 Save and close the document
67 Quit the Word application
69 Then, you will see two new documents in the directory of the application:
70 Sample1.docx and Sample2.docx. Both documents have the following content.
74 Sample2.docx additionally has this table in the document.
82 Step4. In Windows Task Manager, confirm that the winword.exe process does not
83 exist, i.e. the Microsoft Word intance was closed and cleaned up properly.
86 /////////////////////////////////////////////////////////////////////////////
89 VBAutomateWord - CSAutomateWord - CppAutomateWord
91 These examples automate Microsoft Word to do the same thing in different
92 programming languages.
95 /////////////////////////////////////////////////////////////////////////////
98 Step1. Create a Console application and reference the Word Primary Interop
99 Assembly (PIA). To reference the Word PIA, right-click the project file
100 and click the "Add Reference..." button. In the Add Reference dialog,
101 navigate to the .NET tab, find Microsoft.Office.Interop.Word 12.0.0.0 and
104 Step2. Import and rename the Excel interop namepace:
106 Imports Word = Microsoft.Office.Interop.Word
108 Step3. Start up a Word application by creating a Word.Application object.
110 oWord = New Word.Application()
112 Step4. Get the Documents collection from Application.Documents and call its
113 Add function to create a new document. The Add function returns a Document
116 Step5. Insert a paragraph.
118 oParas = oDoc.Paragraphs
120 oParaRng = oPara.Range
121 oParaRng.Text = "Heading 1"
122 oFont = oParaRng.Font
124 oParaRng.InsertParagraphAfter()
126 Step6. Insert a table.
128 The following code has the problem that it invokes accessors which will also
129 create RCWs and reference them. For example, calling Document.Bookmarks.Item
130 creates an RCW for the Bookmarks object. If you invoke these accessors via
131 tunneling as this code does, the RCWs are created on the GC heap, but the
132 references are created under the hood on the stack and are then discarded. As
133 such, there is no way to call MarshalFinalReleaseComObject on those RCWs. To
134 get them to release, you would either need to force a garbage collection as
135 soon as the calling function is off the stack (at which point these objects
136 are no longer rooted) and then call GC.WaitForPendingFinalizers, or you would
137 need to change the syntax to explicitly assign these accessor objects to a
138 variable that you would then explicitly call Marshal.FinalReleaseComObject on.
140 oBookmarkRng = oDoc.Bookmarks.Item("\endofdoc").Range
142 oTable = oDoc.Tables.Add(oBookmarkRng, 5, 2)
143 oTable.Range.ParagraphFormat.SpaceAfter = 6
145 For r As Integer = 1 To 5
146 For c As Integer = 1 To 2
147 oTable.Cell(r, c).Range.Text = "r" & r & "c" & c
151 ' Change width of columns 1 & 2
152 oTable.Columns(1).Width = oWord.InchesToPoints(2)
153 oTable.Columns(2).Width = oWord.InchesToPoints(3)
155 Step7. Save the document as a docx file and close it.
157 Dim fileName As String = Path.GetDirectoryName( _
158 Assembly.GetExecutingAssembly().Location) & "\Sample1.docx"
159 oDoc.SaveAs(fileName, Word.WdSaveFormat.wdFormatXMLDocument)
162 Step8. Quit the Word application.
166 Step9. Clean up the unmanaged COM resource. To get Word terminated rightly,
167 we need to call Marshal.FinalReleaseComObject() on each COM object we used.
168 We can either explicitly call Marshal.FinalReleaseComObject on all accessor
171 ' See Solution1.AutomateWord
172 If Not oFont Is Nothing Then
173 Marshal.FinalReleaseComObject(oFont)
176 If Not oParaRng Is Nothing Then
177 Marshal.FinalReleaseComObject(oParaRng)
180 If Not oPara Is Nothing Then
181 Marshal.FinalReleaseComObject(oPara)
184 If Not oParas Is Nothing Then
185 Marshal.FinalReleaseComObject(oParas)
188 If Not oDoc Is Nothing Then
189 Marshal.FinalReleaseComObject(oDoc)
192 If Not oDocs Is Nothing Then
193 Marshal.FinalReleaseComObject(oDocs)
196 If Not oWord Is Nothing Then
197 Marshal.FinalReleaseComObject(oWord)
201 and/or force a garbage collection as soon as the calling function is off the
202 stack (at which point these objects are no longer rooted) and then call
203 GC.WaitForPendingFinalizers.
205 ' See Solution2.AutomateWord
207 GC.WaitForPendingFinalizers()
208 ' GC needs to be called twice in order to get the Finalizers called
209 ' - the first time in, it simply makes a list of what is to be
210 ' finalized, the second time in, it actually is finalizing. Only
211 ' then will the object do its automatic ReleaseComObject.
213 GC.WaitForPendingFinalizers()
216 /////////////////////////////////////////////////////////////////////////////
219 MSDN: Word 2007 Developer Reference
220 http://msdn.microsoft.com/en-us/library/bb244391.aspx
222 How to automate Word from Visual Basic .NET to create a new document
223 http://support.microsoft.com/kb/316383/
226 /////////////////////////////////////////////////////////////////////////////